.TITLE BSDRV .IDENT /01.02/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; VERSION 01.02 ; ; M. B. GROSSMAN 15-JUL-79 ; ; DT03/DT07 BUS SWITCH ; ; MODIFIED BY: ; ; B. S. MCCARTHY 1-FEB-80 ; ; BM058 -- UPDATE COMPLEMENT TABLE ($CRMTB) WHEN ; UPDATING CPU RUN MASK TABLE ($URMTB) ; ; B. S. MCCARTHY 1-MAR-82 ; ; BM242 -- DON'T LOG BUS SWITCH ERRORS ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$,UCBDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS UCBDF$ ;DEFINE UCB OFFSETS ; ; ; DEVICE CONTROL STATUS REGISTER BIT ASSIGNMENTS ; TMO= 100000 ;TIMEOUT ERROR PWF= 040000 ;POWERFAIL ERROR EXTINT= 010000 ;EXTERNAL INTERRUPT CONN= 000200 ;CONNECT STATUS IE= 000100 ;INTERRUPT ENABLE REQ= 000001 ;REQUEST BIT RES= 001000 ;RESET BIT ; ; SPECIAL UCB OFFSETS ; U.ASTA=U.CNT+2 ;AST ADDRESS OFFSET (U.CNT+2) U.ASTE=U.ASTA+2 ;AST ERROR CODE OFFSET (U.CNT+4) ; ; SPECIAL SCB STATUS CODES PWFB=2 ;BUSY DUE TO POWER FAILURE QIOB=1 ;BUSY DUE TO NORMAL QIO ; ; DRIVER DISPATCH TABLE ; DDT$ BS,D$$T07 ;+ ; **-BSINI-DT03/DT07 BUS SWITCH INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN ; AN I/O REQUEST IS QUEUED AND AT THE END OF A PREVIOUS ; I/O OPERATION TO PROPAGATE THE EXECUTION OF THE DRIVER. ; IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN ; ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST ; IF THE CONTROLLER IS BUSY A RETURN TO THE CALLER IS ; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN ; THE NEXT I/O OPERATION IS INITIATED. THIS CYCLE ; CONTINUES UNTIL THE I/O QUEUE IS EMPTY. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; OUTPUTS: ; ; IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O ; REQUEST IS WAITING TO BE PROCESSED, ; THEN THE REQUEST IS DEQUEUED AND THE I/O OPER- ; ATION IS INITIATED. ;- .ENABL LSB BSINI: GTPKT$ BS,,,,T ;GET NEXT I/O PACKET TO PROCESS ; ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT : ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK. ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; DT03/DT07 BUS SWITCH I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK. ; WD. 03 -- POINTER TO 2ND LUN WORD IN REQUESTOR TASK HEADER. ; WD. 04 -- CONTENTS OF 1ST LUN WORD IN REQUESTOR TASK HEADER. ; WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB). ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; IF FUNCTION IO.DIS: ; WD. 12 -- TIMEOUT. (LESS THAN 254 SECONDS) ; WD. 13 -- CPU. (PORT NUMBER) ; IF FUNCTION IO.CON: ; WD. 12 -- RETRY COUNT (-1 MEANS INFINITE RETRY) ; WD. 13 --TARGET CPU (CLOSELY COUPLED CPU'S LETTER) ; IF FUNCTION IO.ATT: ; WD. 12 -- AST ADDRESS. ; IF FUNCTION IO.SWI: ; WD. 12 -- CPU (CLOSELY COUPLED CPU'S LETTER) ; ; ;+ ; THE FOLLOWING ROUTINE INITIALIZES THE I/O FUNCTIONS HANDLED ; BY THIS DRIVER. ( ATTACH,DETACH,CSR,CONNECT,DISCONNECT ; AND SWITCH) THE SWITCH FUNCTION COMBINES VARIOUS SEGMENTS ; OF THE DISCONNECT AND CONNECT CODE ALONG WITH UNIQUE CODE ; OF ITS OWN IN ORDER TO PERFORM A TRANSFER OF THE BUS BETWEEN ; TWO CLOSELY COUPLED PROCESSORS. IT FIRSTS BEGINS A DISCONNECT ; FUNCTION STOPPING PRIOR TO RELEASING THE BUS FROM THE CPU THAT ; IS TO BE DISCONNECTED. IT THEN ISSUES A REQUEST ON THE CPU ; THAT IS TO BE CONNECTED. WHEN THE CPU TO BE DISCONNECTED ; RECEIVES AN EXTERNAL INTERRUPT FROM THE SPECIFIED CONNECT ; CPU IT THEN COMPLETES THE DISCONNECT AND ALLOWS THE NEWLY ; CONNECTED CPU TO RECEIVE CONTROL OF THE BUS ;- ; CMPB #IO.DET/^D<256>,I.FCN+1(R1) ;DETACH FUNCTION? BNE 10$ ;IF NE NO CLR U.ASTA(R5) ;CLEAR AST ADDRESS CLR U.ASTE(R5) ;CLEAR AST ERROR CODE TST S.KRB(R4) ;IS PROCESSOR CONNECTED? BEQ 15$ ;IF EQ NO MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS BR 50$ ;DISCONNECT CPU 10$: CMPB #IO.ATT/^D<256>,I.FCN+1(R1) ; ATTACH FUNCTION? BNE 20$ ;IF NE NO MOV I.PRM(R1),U.ASTA(R5) ;STORE AST ADDRESS MOV #1,U.ASTE(R5) ;STORE DEFAULT AST ERROR 15$: JMP IOSUC ;COMPLETE I/O 20$: MOV #IE.BAD&377,R0 ;ASSUME BAD PARAMETERS CMPB #IO.CON/^D<256>,I.FCN+1(R1) ; CONNNECT FUNCTION? BEQ 110$ ;IF EQ YES TST S.KRB(R4) ;CONNECTED? BEQ 44$ ;IF EQ NO MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS CMPB #IO.CSR/^D<256>,I.FCN+1(R1) ; CSR FUNCTION? BNE 30$ ;IF NE NO MOV (R2),R1 ;PREPARE FOR CSR TRANSFER BR 15$ 30$: CMPB #IO.SWI/^D<256>,I.FCN+1(R1) ; SWITCH FUNCTION ? BNE 40$ ;IF NE NO MOV I.PRM(R1),R3 ;STORE CPU LETTER BR 120$ ;START CONNECT PROCESS 40$: CMP #IO.DIS,I.FCN(R1) ;REGULAR DISCONNECT? BEQ 50$ ;IF EQ YES, ELSE SPEC. DISCONNECT CMP #3,I.PRM+2(R1) ;PORT # LEGAL BLO 44$ ;IF LO NO CMP I.PRM(R1),#254. ;TIMEOUT LESS THAN MAX. BLO 45$ ;IF LO NO 44$: JMP IOEND 45$: MOVB I.PRM(R1),S.CTM(R4) ;SET TIMEOUT BNE 48$ ;IF NE USE SPEC. VALUE MOVB S.ITM(R4),S.CTM(R4) ;ELSE USE DEFAULT 48$: RETURN PMATCH: ;REF LABEL 50$: MOV #IS.SUC&377,R0 ;SUCCESSFUL DISCON: BIS #RES,(R2) ;RESET BUS BIC #IE!REQ,(R2) ;CLEAR INT. ENABLE AND REQ. BIC U.CW3(R5),@$CPURM;UPDATE PROCESSOR URM BIS U.CW3(R5),@$CPCRM ;UPDATE COMPLEMENT OF RUN MASK CMPB #QIOB,S.STS(R4) ;REAL I/O? BNE 75$ ;IF NE NO CMPB #IO.SWI/^D<256>,I.FCN+1(R1) ; SWITCH FUNCTION? BNE 70$ ;IF NE NO MOV I.PRM+10(R1),S.URM(R4) ;RESTORE CONNECT CPU'S URM MOV I.PRM+12(R1),S.KRB(R4) ;RESTORE CONNECT ; CPU'S KRB POINTER CALL $CFORK ;SWITCH TO CONNECT CPU MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS BIT #CONN,(R2) ;IS CPU CONNECTED? BEQ 60$ ;IF EQ NO JMP IOCMP 60$: MOV #IE.CNR&377,R0 ;CONNECTION FAILURE 70$: CLR S.KRB(R4) ;PUT SB OFFLINE BR 44$ ;END 75$: CLR S.KRB(R4) ;PUT SB OFFLINE TST U.ASTA(R5) ;IS AST ADDRESS SPECIFIED? BEQ 48$ ;IF EQ NO MOV #6*2,R1 ;LENGTH OF AST BLOCK CALL $ALOCB ;ALLOCATE AN AST BLOCK BCS 48$ ;IF ALLOCATE FAIL JUST RETURN TST (R0)+ ;SKIP OVER LINK WORD MOV R1,(R0)+ ;SAVE SIZE OF AST BLOCK MOV R0,R1 ;SAVE BEGINNING ADDRESS OF CMP -(R1),-(R1) ; AST BLOCK MOV #10*2,(R0)+ ;SAVE BYTES TO ALLOCATE ON STACK MOV U.ASTA(R5),(R0)+ ;SAVE AST TRAP ADDRESS MOV #1,(R0)+ ;SAVE NUMBER OF AST PARAMETERS MOV U.ASTE(R5),(R0) ;SAVE ERROR NUMBER MOV U.ATT(R5),R0 ;GET ADDRESS OF TASK'S TCB CALLR $QASTT ;INSERT AST BLOCK IN AST QUEUE ; ;THE FOLLOWING CODE INSURES THAT THE CPU TO BE ;CONNECTED IS ONLINE, HAS ACCESS TO THE SWITCH ;AND THAT ITS KRB IS ONLINE. ; 110$: MOVB I.PRM+2(R1),R3 ;STORE CPU LETTER IF TARGET CPU BNE 120$ ;IF NE YES MOVB $PROC2,R3 ;STORE CPU WORD OFFSET BR 125$ 120$: SUB #101,R3 ;CONVERT ASCII LETTER TO # BLT 121$ ;CPU LETTER LESS THAN 'A'- ERROR ASL R3 ;CONVERT TO WORD OFFSET BIT $BTMSK(R3),$URMST ;IS CPU ONLINE? BNE 125$ ;IF NE YES MOV #IE.OFL&377,R0 ; 121$: JMP IOEND 125$: MOV $BTMSK(R3),R3 ;STORE TARGET CPU MASK WORD MOV R4,R1 ADD #S.KTB,R1 ;STORE ADDRESS OF FIRST KTB WORD 140$: MOV (R1)+,R2 ;MOVE ADDRESS OF KRB INTO R2 BEQ 121$ ;ADDRESS TERMINATOR? IF EQ YES BIT R3,K.URM(R2) ;DOES CPU HAVE ACCESS? BEQ 140$ ;IF EQ NO MOV #IE.OFL&377,R0 ;ASSUME OFFLINE KRB BIT #KS.OFL,K.STS(R2) ;IS KRB OFFLINE? BNE 121$ ;IF NE YES MOV S.PKT(R4),R1 ;RESTORE I/O PACKET CMPB #IO.SWI/^D<256>,I.FCN+1(R1) ; SWITCH FUNCTION? BNE 150$ ;IF NE NO ; ;NOTE!!! THE PORT NUMBER OF THE DT07 THAT CORRESPONDS ;TO A SPECIFIC CPU/KRB IS STORED IN THE LOW BYTE OF K.PRM ; MOVB K.PRM(R2),I.PRM+2(R1) ;STORE CONN. CPU PORT # MOV S.URM(R4),I.PRM+4(R1) ;STORE DISCONNECT CPU'S URM MOV S.KRB(R4),I.PRM+6(R1) ;STORE DIS. CPU'S KRB POINTER 150$: MOV I.PRM(R1),U.CW2(R5) ;STORE RETRY COUNT MOV K.URM(R2),S.URM(R4) ;STORE URM IN SCB MOV R2,S.KRB(R4) ;STORE POINTER TO KRB IS SCB CALL $CFORK ;SWITCH, IF REQ., TO PROPER CPU MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS MOV #IE.BAD&377,R0 ;ASSUME CPU ALREADY CONNECTED BIT #CONN,(R2) ;IS CPU CONNECTED? BEQ 160$ ;F EQ NO JMP IOCMP ;COMPLETE CONNECTION IF REQUIRED 160$: MOV S.PKT(R4),R1 ;RESTORE I/O PACKET ADDRESS CMPB #IO.SWI/^D<256>,I.FCN+1(R1) ; SWITCH FUNCTION? BNE CONBS ;IF NE NO MOVB S.ITM(R4),S.CTM(R4) ;SET TIMEOUT ; ;THE SWITCH FUNCTION ISSUES A CONNECT REQUEST ON THE ;CPU TO BE CONNECTED AFTER RESTORING THE DISCONNECT ;CPU'S URM TO S.URM. THIS INSURES THAT THE INTERRUPT ;THAT WILL BE CAUSED BY THE DISCONNECT CPU'S EXTERNAL ;INTERRUPT BIT BEING SET WILL CALL THE DISCONNECT CPU. ; MOV S.URM(R4),I.PRM+10(R1) ;STORE CONNECT CPU'S URM MOV I.PRM+4(R1),S.URM(R4) ;RESTORE DIS. CPU'S URM BIS #S2.ACT,S.ST2(R4) ;SET CONTROLLER ACTIVE FLAG BIS #REQ,(R2) ;ASSERT REQUEST RETURN ;AWAIT CONNECTED CPU'S INTERRUPT CONBS: MOVB S.ITM(R4),S.CTM(R4) ;SET TIMEOUT BIS #S2.ACT,S.ST2(R4) ;SET CONTROLLER ACTIVE FLAG BIS #IE!REQ,(R2) ;ENABLE INTERRUPTS ASSERT REQ. RETURN .DSABL LSB ;+ ; THE POWERFAIL ROUTINE ATTEMPTS TO RESTORE THE STATE ; OF THE SYSTEM PRIOR TO THE POWERFAIL. IF I/O WAS EXECUTING ; THE TIMEOUT IS RESET AND THE PREVIOUS OPERATION CONTINUED. ; IF THE SB WAS PREVIOUSLY CONNECTED TO THIS PROCESSOR AND ; NO I/O WAS EXECUTING A CHECK FOR CONNECTION IS MADE AND A ; RECONNECT SEQUENCE BEGUN IF NEEDED. ;- BSPWF: TST S.KRB(R4) ;WAS SWITCH CONNECTED? BGT 5$ ;IF GT YES JMP BSINI 5$: TSTB S.STS(R4) ;IS SWITCH CURRENTLY BUSY BEQ 20$ ;IF EQ NO MOVB S.ITM(R4),S.CTM(R4) ;RESET TIMEOUT 10$: RETURN 20$: MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS BIT #CONN,(R2) ;IS CPU CONNECTED TO BUS? BNE 10$ ;IF NE YES MOV #2,U.ASTE(R5) ;ASSUME FAILURE TO CONNECT MOVB #PWFB,S.STS(R4) ;SET STATUS TO BUSY BR CONBS ;CONNECT SWITCH ;+ ; **-$BSINT DT03/DT07 BUS SWITCH INTERRUPTS ; INTERRUPTS CAN BE ISSUED BY THE BUS SWITCH ; FOR DEVICE POWERFAIL, A REQUEST FOR THE ; BUS BY ANOTHER CPU, TIMEOUT OF A REQUEST ; FOR CONNECT, TIMEOUT OF THE WATCHDOG TIMER AND UPON ; RECEIVING A CONNECT TO THE SWITCHED BUS. ;- INTSE$ BS,PR7,D$$T07 ;;;SAVE REGISTERS & SET PRIORITY MOV U.SCB(R5),R4 ;;;GET ADDRESS OF SCB MOV R1,-(SP) ;;;STORE R1 CMPB #QIOB,S.STS(R4) ;;;REAL I/O? BNE 10$ ;;;IF NE NO MOV S.PKT(R4),R1 ;;;GET I/O PACKET ADDRESS CMPB #IO.SWI/^D<256>,I.FCN+1(R1) ;;; SWITCH FUNCTION? BNE 10$ ;;;IF NE NO MOV S.KRB(R4),I.PRM+12(R1) ;;;STORE CONNECT CPU'S ;;; KRB POINTER MOV I.PRM+6(R1),S.KRB(R4) ;;;RESTORE DISCONNECT CPU'S KRB 10$: MOV @S.KRB(R4),R1 ;;;STORE CSR ADDRESS TST (R1) ;;;WATCHDOG OR REQUEST TIMER SET? BMI 60$ ;;;IF MI YES BIT #EXTINT,(R1) ;;;EXTERNAL INTERRUPT? BEQ 50$ ;;;IF EQ NO ; ;THIS SECTION INSURES THAT IF AN EXTERNAL INTERRUPT ;BIT IS SET THAT IT WILL BE CLEARED IN TIME TO PREVENT ;THE TIMEOUT LOSS OF THE BUS. INITIAL PROCESSING IS DONE ;AT PRIORITY 7 TO INSURE THAT THE TIME LIMIT WILL BE ;MET AND THAT THE EXECUTIVE TIMEOUT COUNT IS NOT RESET ; MOV (R1),-(SP) ;;;STORE CSR VALUE BIC #EXTINT,(R1) ;;;CLEAR EXTERNAL INTERRUPT MOV R2,-(SP) ;;;STORE R2 MOV R3,-(SP) ;;;STORE R3 CMPB #QIOB,S.STS(R4) ;;;IS REAL I/O PENDING BNE 40$ ;;;IF NE NO MOV S.PKT(R4),R2 ;;;GET I/O PACKET ADDRESS CMPB #IO.SWI/^D<256>,I.FCN+1(R2) ;;;IS THIS AN IO.SWI? BNE 20$ ;;;IF NE NO BIT #74,-4(SP) ;;; IS THIS A DT03? BNE 30$ ;;;IF NE NO BR 35$ ;;; 20$: CMPB #IO.DIS/^D<256>,I.FCN+1(R2) ;;;IS THIS AN IO.DIS? BNE 40$ ;;;IF NE NO 30$: MOV #4,R3 ;;;MOVE 4 INTO R3 ASH I.PRM+2(R2),R3 ;;;CREATE CPU MASK BIT R3,-4(SP) ;;;IS THIS CORRECT CPU? BEQ 40$ ;;;IF EQ NO ; ;THIS SECTION IS ENTERED ONLY IF THE PENDING FUNCTION IS A ;SWITCH OR DISCONNECT AND THEN ONLY IF THE CPU CAUSING ;THE EXTERNAL INTERRUPT WAS THE SPECIFIED ONE. ;NOTE:IF SWITCH IS A DT03 NO CHECKING OF THE SOURCE OF THE ;INTERRUPT IS POSSIBLE AND THE BUS IS NEVER RELEASED IN ;THE CASE WHERE THE FUNCTION WAS A DISCONNECT AND THE BUS ;IS ALWAYS RELEASED IN THE CASE WHERE THE FUNCTION WAS ;A SWITCH. ; 35$: MOV (SP)+,R3 ;;;RESTORE R3 MOV (SP)+,R2 ;;;RESTORE R2 TST (SP)+ ;;;RESTORE STACK MOV (SP)+,R1 ;;;RESTORE R1 CALL $FORK ;;;CREATE A SYSTEM PROCESS MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS JMP PMATCH ;DISCONNECT 40$: MOV (SP)+,R3 ;;;RESTORE R3 MOV (SP)+,R2 ;;;RESTORE R2 TST (SP)+ ;;;RESTORE STACK MOV (SP)+,R1 ;;;RESTORE R1 45$: RETURN 50$: BIT #PWF,(R1) ;;;BS POWER LOSS? BEQ 120$ ;;;IF EQ NO ; ;THIS SECTION HANDLES THE CASE OF AN INTERRUPT CAUSED ;BY A POWER FAILURE ON THE SWITCHED BUS. PENDING I/O, ;EXCEPT A DISCONNECT, IS TERMINATED AND A DISCONNECT ;IS PERFORMED. ; BIC #IE,(R1) ;;; CLEAR INTERUPT ENABLE MOV (SP)+,R1 ;;;RESTORE R1 CALL $FORK ;;;CREATE A SYSTEM PROCESS MOV @S.KRB(R4),R2 ;PUT CSR ADDRESS IN R2 CMPB #QIOB,S.STS(R4) ;IS REAL I/O IN PROGRESS? BEQ 55$ ;IF EQ YES MOV #3,U.ASTE(R5) ;AST ERROR CODE=3, POWERFAIL CLRB S.STS(R4) ;RESET STATUS BR 75$ 55$: MOV S.PKT(R4),R1 ;GET ADDRESS OF I/O PACKET CMPB #IO.DIS/^D<256>,I.FCN+1(R1) ;IO.DIS? BEQ 45$ ;IF EQ YES MOV #IE.ABO&377,R0 ;ELSE ABORT OPERATION MOV #401,R2 ;NO RETRY COUNT CALL $IODON ;TERMINATE I/O MOV U.SCB(R5),R4 ;STORE SCB ADDRESS LOST IN IODON MOV S.PKT(R4),R1 ;GET ADDRESS OF I/O PACKET MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS BR 75$ ; ;THIS SECTION HANDLES AN INTERRUPT CAUSED BY THE TIMEOUT ;BIT BEING SET. IF THIS WAS CAUSED BY A FAILURE TO CONNECT ;AFTER ISSUING A REQUEST, THE RETRY COUNT IS CHECKED AND ;THE PROPER ACTION TAKEN. IF THIS WAS CAUSED BY A FAILURE ;TO RECONNECT AFTER POWERFAIL A DISCONECT IS INITIATED ;AND AN OPTIONAL AST ISSUED. ; 60$: BIC #TMO!EXTINT!IE,(R1) ;;;CLEAR CSR BITS MOV (SP)+,R1 ;;;RESTORE R1 CALL $FORK ;;;CREATE A SYSTEM PROCESS MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS CMPB #QIOB,S.STS(R4) ;WAS THIS A CONNECT? BEQ 100$ ;IF EQ YES CLRB S.STS(R4) ;RESET STATUS CMP U.ASTE(R5),#2 ;IS ERROR A POWERFAIL RECONNECT? BEQ 75$ ;IF EQ YES MOV #1,U.ASTE(R5) ;SET AST ERROR =1, TIMEOUT ERROR 75$: JMP DISCON ;PERFORM A DISCONNECT 100$: MOV S.PKT(R4),R1 ;GET ADDRESS OF I/O PACKET TST U.CW2(R5) ;IS RETRY COUNT =0? BEQ 110$ ;IF EQ YES CMP #-1,U.CW2(R5) ;IS IT NEG. 1? BEQ 105$ ;IF EQ YES DEC U.CW2(R5) ;DECREASE RETRY COUNT 105$: JMP CONBS ;TRY AGAIN 110$: MOV #IE.CNR&377,R0 ;CONNECT FAILURE BR 75$ 120$: MOV (SP)+,R1 ;;;RESTORE R1 CALL $FORK ;;;CREATE A SYSTEM PROCESS MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS BIT #CONN,(R2) ;IS BUS PHYSICALY CONN.? BEQ 75$ ;IF EQ NO IOCMP: BIS #IE,(R2) ;ENSURE INTERRUPTS ENABLED BIS U.CW3(R5),@$CPURM;SET CPU URM BIC U.CW3(R5),@$CPCRM ;UPDATE COMPLEMENT OF RUN MASK CMPB #QIOB,S.STS(R4) ;WAS THIS A I/O CONNECT? BEQ IOSUC ;IF EQ YES CLRB S.STS(R4) ;RESET STATUS MOV #1,U.ASTE(R5) ;RESTORE ERROR CODE MOV U.CW3(R5),$PFURM;POWERFAIL UNIBUS INCB $PWRFL+1 ; ATTACHED DEVICES RETURN IOSUC: MOV #IS.SUC&377,R0 ;I/O WAS A SUCCESS IOEND: MOV #401,R2 ;NO RETRIES ATTEMPTED CALL $IODON ;FINISH I/O OPERATION JMP BSINI ;NEXT REQUEST ;+ ; TIMEOUT IS USED BY IO.DIS TO LIMIT THE AMOUNT OF TIME WAITED ; FOR A SPECIFIED LOOSELY COUPLED CPU TO ISSUE A CONNECT REQUEST. ; IF THE CORRECT CPU DOES NOT RESPOND A TIMEOUT ERROR ; IS GENERATED. ALL OTHER TIMEOUT ENTRIES INDICATE ; HARDWARE OR POWER PROBLEMS. ;- BSOUT: ;;;REFERENCE LABEL MOV #IE.TMO&377,R0 ;TIMEOUT ERROR MOV S.PKT(R4),R1 ;GET ADDRESS OF I/O PACKET CMPB #PWFB,S.STS(R4) ;IS THIS A POWERFAIL ENTRY? BNE 5$ ;IF NE NO CLRB S.STS(R4) ;CLEAR STATUS BR 10$ ;DISCONNECT 5$: CMPB #IO.CON/^D<256>,I.FCN+1(R1) ; CONNECT FUNCTION? BNE 20$ ;IF NE NO 10$: MOV @S.KRB(R4),R2 ;STORE CSR ADDRESS JMP DISCON 20$: CMPB #IO.SWI/^D<256>,I.FCN+1(R1) ; SWITCH FUNCTION? BEQ 30$ ;IF EQ YES, ; ELSE DIS. TO SPEC. CPU TMO BIS #IE,(R2) ;RE-ENABLE INTERRUPTS BR IOEND ;END WAIT 30$: MOV I.PRM+6(R1),S.KRB(R4) ;RESTORE DISCONNECT ; CPU'S KRB POINTER BR IOEND ;+ ; CANCEL I/O WILL ZERO AN IO.CON RETRY COUNT ; OR SET S.CTM (TIMEOUT COUNT) TO ONE FOR AN IO.DIS. ; TERMINATION THEN OCCURS THROUGH NORMAL CHANNELS. ;- BSCAN: MOV S.PKT(R4),R1 ;;;GET I/O PACKET ADDRESS CMPB #IO.DIS/^D<256>,I.FCN+1(R1) ;;; DISCONNECT? BNE 10$ ;;;IF NE NO MOVB #1,S.CTM(R4) ;;;SET TIMEOUT TO 1 RETURN ;;; 10$: CMPB #IO.CON/^D<256>,I.FCN+1(R1) ;;; CONNECT? BNE 20$ ;;;IF NE NO MOVB S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT CLR U.CW2(R5) ;;;SET RETRY COUNT TO ZERO 20$: RETURN ;;; .END